package com.suray.wcs.res.msgparse;

import com.suray.basic.wcs.utils.Crc16;
import lombok.Data;

import java.util.Arrays;

/**
 * 接受基本信息
 *
 *
 * @author Doofy&xuhang
 */
@Data
public class ReceiveMsgHeartBeatBase extends ResultBase {

    private int index = 32;
    /**
     * 头帧 2字节
     */
    private  int firstFrame = 0x02fd;
    /**
     * 头长度 2字节
     */
    private  int firstMsgLen = 42;
    /**
     * 当前坐标 3字节
     */
    private  int currentLocation;
    /**
     * 当前小车形式所在的段序号 1字节
     */
    private  int curentSegment;
    /**
     * 当前段终点坐标 2字节
     */
    private  int segmentLocation;
    /**
     * 返回当前条码值 4字节
     */
    private  int curBarcode;
    /**
     * 小车状态 1字节
     */
    private  int carStatus;
    /**
     * 托板状态 1字节
     */
    private  int palletStatus;
    /**
     * 换向状态 1字节
     */
    private  int reserveStatus;
    /**
     * 行驶方向 1字节
     */
    private  int driveDirection;
    /**
     * 电量 1字节
     */
    private  int electric;

    /**
     * 尾长度 2字节
     */
    private  int endMsgLen = 42;
    /**
     * 尾帧 2字节
     */
    private  int endFrame = 0x03fc;
    /**
     * 校验信息是否正确
     */
    private boolean isRight = false;

    @Override
    public boolean isRight() {
        return isRight;
    }

    public ReceiveMsgHeartBeatBase(byte[] bs) {
        // 对接收报文的长度进行校验
        if (null == bs) {
            throw new RuntimeException("接收报文为空");
        }
        if (bs.length < firstMsgLen) {
            throw new RuntimeException("报文长度不合法，当前长度:" + bs.length + ",报文内容" + Arrays.toString(bs));
        }
        this.deviceType = getValue(bs, 8);
        this.deviceNo = getValue(bs, 8);
        this.mode = getValue(bs, 8);
        super.isSameMapVersion = getValue(bs, 8);
        super.taskNo = getValue(bs, 8);
        super.taskType = getValue(bs, 8);
        this.taskResult = getValue(bs, 8);
        this.cmdNo = getValue(bs, 8);
        this.cmdExecuteResult = getValue(bs, 8);
        this.cmdExecuteResultParam = getValue(bs, 32);
        this.currentLocation = getValue(bs, 24);
        this.curentSegment = getValue(bs, 8);
        this.segmentLocation = getValue(bs, 16);
        this.curBarcode = getValue(bs, 32);
        this.carStatus = getValue(bs, 8);
        this.palletStatus = getValue(bs, 8);
        this.reserveStatus = getValue(bs, 8);
        this.driveDirection = getValue(bs, 8);
        this.electric = getValue(bs, 8);
        this.statusMessage = getValue(bs,8);
        this.barrierAtOne = getValue(bs,4);
        this.barrierAtTwo = getValue(bs,4);
        this.barrierAtThree = getValue(bs,4);
        this.barrierAtFour = getValue(bs,4);
        byte codeOffset = (byte) getValue(bs,8);

        if (codeOffset == -100) {
            offsetGroundCode = 490;
        } else if (codeOffset == 0) {
            offsetGroundCode = 500;
        } else if (codeOffset == 100) {
            offsetGroundCode = 510;
        } else {
            offsetGroundCode = 0xFF;
        }

        index += 16;
        this.isRight = isCRC16Right(bs, bs.length - 4, getValue(bs, 16));
    }

    private int getValue(byte[] bs, int size) {
        int value = MsgTransferUtil.getValues(bs, index, size);
        index += size;
        return value;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getFirstFrame() {
        return firstFrame;
    }

    public int getFirstMsgLen() {
        return firstMsgLen;
    }


    @Override
    public int getCmdExecuteResult() {
        return cmdExecuteResult;
    }

    public int getCurrentLocation() {
        return currentLocation;
    }

    public int getCurentSegment() {
        return curentSegment;
    }

    public int getSegmentLocation() {
        return segmentLocation;
    }

    public int getCurBarcode() {
        return curBarcode;
    }

    public int getCarStatus() {
        return carStatus;
    }

    public int getPalletStatus() {
        return palletStatus;
    }

    public int getReserveStatus() {
        return reserveStatus;
    }

    public int getDriveDirection() {
        return driveDirection;
    }

    public int getElectric() {
        return electric;
    }

    public int getEndMsgLen() {
        return endMsgLen;
    }

    public int getEndFrame() {
        return endFrame;
    }

    private boolean isCRC16Right(byte[] bs, int len, int crc16) {
        return Crc16.CRC_XModem(bs, len) == crc16;
    }

}
